<template>
  <el-container>
    <el-header class="csv-header">
      <div class="controls">
        <div class="file-controls">
          <el-button type="primary" @click="handleExport" :disabled="!hasData">
            导出 CSV
          </el-button>
          <input
            ref="fileInput"
            type="file"
            accept=".csv"
            @change="handleFileChange"
            style="display: none"
          />
          <el-button @click="triggerFileInput"> 导入 CSV </el-button>
          <el-button @click="clearTable" type="danger" plain>
            清空表格
          </el-button>
        </div>
        <div class="table-controls">
          <el-button @click="addRow" type="success" plain size="small">
            +行
          </el-button>
          <el-button
            @click="removeRow"
            type="warning"
            plain
            size="small"
            :disabled="rows <= minRows"
          >
            -行
          </el-button>
          <el-button @click="addColumn" type="success" plain size="small">
            +列
          </el-button>
          <el-button
            @click="removeColumn"
            type="warning"
            plain
            size="small"
            :disabled="cols <= minCols"
          >
            -列
          </el-button>
          <span class="table-info">{{ rows }}行 × {{ cols }}列</span>
        </div>
      </div>
    </el-header>

    <!-- 导入进度条 -->
    <div v-if="importing" class="import-progress">
      <el-progress
        :percentage="importProgress"
        :status="importStatus"
        :stroke-width="6"
      />
      <div class="progress-text">
        {{ importStatusText }}
      </div>
    </div>

    <el-main class="csv-main">
      <div class="virtual-table-container">
        <!-- 虚拟滚动表格内容 - 表头和内容在同一个滚动容器内 -->
        <div
          class="virtual-table-body"
          ref="scrollElement"
          :style="{ height: virtualTableHeight, overflow: 'auto' }"
        >
          <!-- 表头 - 粘性定位 -->
          <div class="table-header-container">
            <div class="header-row">
              <div class="header-cell row-number-header">#</div>
              <div
                v-for="colIndex in cols"
                :key="colIndex"
                class="header-cell table-header"
                :style="{ width: `${dynamicColumnWidth}px` }"
              >
                <div class="header-content">
                  <span>{{ getColumnLabel(colIndex - 1) }}</span>
                  <button
                    v-if="cols > minCols"
                    class="delete-btn delete-col-btn"
                    @click="deleteColumn(colIndex - 1)"
                    :title="`删除 ${getColumnLabel(colIndex - 1)} 列`"
                  >
                    ×
                  </button>
                </div>
              </div>
            </div>
          </div>

          <!-- 虚拟滚动内容区域 -->
          <div
            :style="{
              height: `${totalSize}px`,
              width: '100%',
              position: 'relative',
            }"
          >
            <div
              v-for="virtualRow in virtualRows"
              :key="virtualRow.index"
              :ref="measureElement"
              :style="{
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                height: `${virtualRow.size}px`,
                transform: `translateY(${virtualRow.start}px)`,
              }"
            >
              <div class="table-row">
                <div class="table-cell row-number-cell">
                  <div class="row-number-content">
                    <span>{{ virtualRow.index + 1 }}</span>
                    <button
                      v-if="rows > minRows"
                      class="delete-btn delete-row-btn"
                      @click="deleteRow(virtualRow.index)"
                      :title="`删除第 ${virtualRow.index + 1} 行`"
                    >
                      ×
                    </button>
                  </div>
                </div>
                <div
                  v-for="(cell, colIndex) in tableData[virtualRow.index]"
                  :key="colIndex"
                  class="table-cell data-cell"
                  :style="{ width: `${dynamicColumnWidth}px` }"
                >
                  <input
                    v-model="tableData[virtualRow.index][colIndex]"
                    class="cell-input"
                    @input="onCellChange"
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </el-main>
  </el-container>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from "vue";
import Papa from "papaparse";
import { ElMessage } from "element-plus";
import { useVirtualizer } from "@tanstack/vue-virtual";

// 表格配置
const minRows = 5;
const minCols = 3;
const defaultRows = 20;
const defaultCols = 10;

// 响应式数据
const rows = ref(defaultRows);
const cols = ref(defaultCols);
const tableData = ref<string[][]>([]);
const fileInput = ref<HTMLInputElement>();

// 记录导入的CSV文件名
const importedFileName = ref<string>("");

// 导入进度条相关数据
const importing = ref(false);
const importProgress = ref(0);
const importStatus = ref("");
const importStatusText = ref("准备导入...");

// 真正的流式分批导入配置
const CHUNK_SIZE = 1024 * 1024; // 每次读取1MB
const PROCESS_BATCH_SIZE = 100; // 每批处理100行
const PROCESS_DELAY = 5; // 每批之间延迟5ms

// 分批渲染到表格
const renderDataInBatches = async (data: string[][]) => {
  // 先扩充表格大小
  autoExpandTable(data);

  // 清空现有数据
  initializeTable();

  const totalRows = data.length;
  let processedRows = 0;

  // 分批渲染数据到DOM
  for (let i = 0; i < data.length; i += PROCESS_BATCH_SIZE) {
    const batch = data.slice(i, i + PROCESS_BATCH_SIZE);

    // 处理当前批次
    batch.forEach((row, batchIndex) => {
      const globalRowIndex = i + batchIndex;
      if (globalRowIndex < rows.value) {
        row.forEach((cell, colIndex) => {
          if (colIndex < cols.value) {
            tableData.value[globalRowIndex][colIndex] = cell || "";
          }
        });
      }
    });

    processedRows += batch.length;
    const progress = Math.round((processedRows / totalRows) * 100);
    importProgress.value = progress;
    importStatusText.value = `正在渲染数据... ${processedRows}/${totalRows} 行 (${progress}%)`;

    // 让出主线程，保持界面响应
    await new Promise((resolve) => setTimeout(resolve, PROCESS_DELAY));
  }

  importProgress.value = 100;
  importStatusText.value = `导入完成！`;
};

// 流式读取和分批处理CSV文件
const streamProcessFile = async (file: File) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    let offset = 0;
    let buffer = "";
    let totalProcessed = 0;
    let allRows: string[][] = [];

    const readChunk = () => {
      if (offset >= file.size) {
        // 文件读取完成，处理最后的buffer
        if (buffer.trim()) {
          const finalResult = Papa.parse(buffer, { skipEmptyLines: true });
          if (finalResult.data) {
            allRows.push(...(finalResult.data as string[][]));
          }
        }
        resolve(allRows);
        return;
      }

      const chunk = file.slice(offset, offset + CHUNK_SIZE);
      reader.readAsText(chunk);
    };

    reader.onload = async (e) => {
      const chunkText = e.target?.result as string;
      buffer += chunkText;

      // 找到完整的行（以换行符分割）
      const lines = buffer.split("\n");
      // 保留最后一行（可能不完整）
      buffer = lines.pop() || "";

      if (lines.length > 0) {
        // 解析完整的行
        const chunkData = lines
          .map((line) => {
            const result = Papa.parse(line);
            return result.data[0] as string[];
          })
          .filter(
            (row) => row && row.some((cell) => cell && cell.trim() !== "")
          );

        if (chunkData.length > 0) {
          allRows.push(...chunkData);
          totalProcessed += chunkData.length;

          // 更新进度
          const progress = Math.min(Math.round((offset / file.size) * 100), 99);
          importProgress.value = progress;
          importStatusText.value = `正在读取文件... ${progress}% (已读取 ${totalProcessed} 行)`;

          // 让出主线程
          await new Promise((resolve) => setTimeout(resolve, 1));
        }
      }

      offset += CHUNK_SIZE;
      // 继续读取下一块
      setTimeout(readChunk, 1);
    };

    reader.onerror = () => {
      reject(new Error("文件读取失败"));
    };

    // 开始读取
    readChunk();
  });
};

// 计算属性 - 检查是否有数据
const hasData = computed(() => {
  return tableData.value.some((row) =>
    row.some((cell) => cell && cell.trim() !== "")
  );
});

// 生成列标签 (A, B, C, ..., Z, AA, AB, ...)
const getColumnLabel = (index: number): string => {
  let label = "";
  let num = index;
  while (num >= 0) {
    label = String.fromCharCode(65 + (num % 26)) + label;
    num = Math.floor(num / 26) - 1;
  }
  return label;
};

// 初始化空白表格
const initializeTable = () => {
  tableData.value = Array.from({ length: rows.value }, () =>
    Array(cols.value).fill("")
  );
};

// 调整表格大小
const resizeTable = (newRows: number, newCols: number) => {
  const oldData = tableData.value;

  // 创建新的表格数据
  tableData.value = Array.from({ length: newRows }, (_, rowIndex) => {
    return Array.from({ length: newCols }, (_, colIndex) => {
      // 保留现有数据，新增的单元格填充空字符串
      return (oldData[rowIndex] && oldData[rowIndex][colIndex]) || "";
    });
  });

  rows.value = newRows;
  cols.value = newCols;
};

// 添加行
const addRow = () => {
  const newRow = Array(cols.value).fill("");
  tableData.value.push(newRow);
  rows.value++;
  ElMessage.success(`已添加第 ${rows.value} 行`);
};

// 删除行
const removeRow = () => {
  if (rows.value <= minRows) {
    ElMessage.warning(`最少需要保留 ${minRows} 行`);
    return;
  }
  tableData.value.pop();
  rows.value--;
  ElMessage.success(`已删除最后一行`);
};

// 添加列
const addColumn = () => {
  tableData.value.forEach((row) => {
    row.push("");
  });
  cols.value++;
  ElMessage.success(`已添加第 ${getColumnLabel(cols.value - 1)} 列`);
};

// 删除列
const removeColumn = () => {
  if (cols.value <= minCols) {
    ElMessage.warning(`最少需要保留 ${minCols} 列`);
    return;
  }
  tableData.value.forEach((row) => {
    row.pop();
  });
  cols.value--;
  ElMessage.success(`已删除最后一列`);
};

// 删除指定行
const deleteRow = (rowIndex: number) => {
  if (rows.value <= minRows) {
    ElMessage.warning(`最少需要保留 ${minRows} 行`);
    return;
  }

  // 删除指定行的数据
  tableData.value.splice(rowIndex, 1);
  rows.value--;

  ElMessage.success(`已删除第 ${rowIndex + 1} 行`);
};

// 删除指定列
const deleteColumn = (colIndex: number) => {
  if (cols.value <= minCols) {
    ElMessage.warning(`最少需要保留 ${minCols} 列`);
    return;
  }

  // 删除指定列的数据
  tableData.value.forEach((row) => {
    row.splice(colIndex, 1);
  });
  cols.value--;

  ElMessage.success(`已删除第 ${getColumnLabel(colIndex)} 列`);
};

// 自动扩充表格以适应数据
const autoExpandTable = (data: string[][]) => {
  if (!data || data.length === 0) return;

  const requiredRows = data.length;
  const requiredCols = Math.max(...data.map((row) => row.length));

  const newRows = Math.max(requiredRows, minRows);
  const newCols = Math.max(requiredCols, minCols);

  let expanded = false;

  if (newRows > rows.value) {
    expanded = true;
    console.log(`表格行数从 ${rows.value} 扩展到 ${newRows}`);
  }

  if (newCols > cols.value) {
    expanded = true;
    console.log(`表格列数从 ${cols.value} 扩展到 ${newCols}`);
  }

  if (expanded) {
    resizeTable(newRows, newCols);
    ElMessage.success(`表格已自动扩展至 ${newRows} 行 × ${newCols} 列`);
  }
};

// 触发文件选择
const triggerFileInput = () => {
  fileInput.value?.click();
};

// 处理文件导入
const handleFileChange = async (event: Event) => {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0];

  if (!file) return;

  if (!file.name.toLowerCase().endsWith(".csv")) {
    ElMessage.error("请选择 CSV 文件");
    return;
  }

  // 记录导入的文件名（去掉扩展名）
  importedFileName.value = file.name.replace(/\.csv$/i, "");

  // 检查文件大小
  const fileSizeMB = file.size / (1024 * 1024);
  const isLargeFile = fileSizeMB > 0.1; // 5MB以上认为是大文件

  ElMessage.info(
    `开始处理文件 (${fileSizeMB.toFixed(1)}MB)${
      isLargeFile ? "，使用流式处理..." : ""
    }`
  );

  importing.value = true;
  importProgress.value = 0;
  importStatus.value = "";
  importStatusText.value = "准备读取文件...";

  try {
    let parsedData: string[][];

    if (isLargeFile) {
      // 大文件使用流式读取
      parsedData = (await streamProcessFile(file)) as string[][];
    } else {
      // 小文件使用传统方式
      parsedData = await new Promise((resolve, reject) => {
        Papa.parse(file, {
          complete: (result) => {
            const filtered = (result.data as string[][]).filter((row) =>
              row.some((cell) => cell && cell.trim() !== "")
            );
            resolve(filtered);
          },
          error: reject,
        });
      });
    }

    if (parsedData.length === 0) {
      ElMessage.warning("CSV 文件为空");
      importStatus.value = "exception";
      return;
    }

    // 分批渲染数据
    await renderDataInBatches(parsedData);

    ElMessage.success(`成功导入 ${parsedData.length} 行数据`);
  } catch (error) {
    ElMessage.error("文件处理失败");
    console.error("File processing error:", error);
    importStatus.value = "exception";
    // 如果导入失败，清除文件名记录
    importedFileName.value = "";
  } finally {
    // 延迟隐藏进度条
    setTimeout(() => {
      importing.value = false;
    }, 2000);
  }

  // 清空文件输入
  target.value = "";
};

// 清空表格
const clearTable = () => {
  // 恢复到初始的行列数
  rows.value = defaultRows;
  cols.value = defaultCols;

  // 清除导入文件名记录
  importedFileName.value = "";

  // 重新初始化表格
  initializeTable();

  ElMessage.success(
    `表格已清空并恢复到初始大小 (${defaultRows}行 × ${defaultCols}列)`
  );
};

// 单元格变化事件
const onCellChange = () => {
  // 可以在这里添加数据变化的处理逻辑
};

// 导出功能
const handleExport = () => {
  // 只导出非空行
  const dataToExport = tableData.value.filter((row) =>
    row.some((cell) => cell && cell.trim() !== "")
  );

  if (dataToExport.length === 0) {
    ElMessage.warning("没有可导出的数据");
    return;
  }

  // 找到整个表格的实际列数（基于当前表格的列数）
  // 而不是基于数据的最后非空列，因为可能存在中间列有数据但最后几列为空的情况
  let maxCols = 0;

  // 遍历所有非空行，找到真正需要的最大列数
  dataToExport.forEach((row) => {
    for (let i = row.length - 1; i >= 0; i--) {
      if (row[i] && row[i].trim() !== "") {
        maxCols = Math.max(maxCols, i + 1);
        break;
      }
    }
  });

  // 如果没有找到任何数据，至少保持当前表格的列数
  if (maxCols === 0) {
    maxCols = cols.value;
  }

  // 确保所有行都有相同的列数，空单元格用空字符串填充
  const normalizedData = dataToExport.map((row) => {
    const normalizedRow = [];
    for (let i = 0; i < maxCols; i++) {
      normalizedRow[i] = row[i] !== undefined ? row[i] : ""; // 空单元格用空字符串填充
    }
    return normalizedRow;
  });

  try {
    const csv = Papa.unparse(normalizedData);
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);

    // 根据是否有导入文件名来决定导出文件名
    if (importedFileName.value) {
      // 使用原始文件名
      link.download = `${importedFileName.value}.csv`;
    } else {
      // 使用默认的时间戳命名
      link.download = `data-${new Date().toISOString().split("T")[0]}.csv`;
    }

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(link.href);

    const fileNameInfo = importedFileName.value
      ? `使用原始文件名：${importedFileName.value}.csv`
      : "使用默认文件名";

    ElMessage.success(
      `成功导出 ${normalizedData.length} 行 ${maxCols} 列数据 (${fileNameInfo})`
    );
  } catch (error) {
    ElMessage.error("导出失败");
    console.error("Export error:", error);
  }
};

// 虚拟滚动相关
const scrollElement = ref<HTMLElement>();
const virtualTableHeight = ref("600px");

// 使用 computed 创建响应式的虚拟化器
const virtualizer = computed(() => {
  // 只有当 scrollElement 存在且 tableData 有数据时才创建虚拟化器
  if (!scrollElement.value || tableData.value.length === 0) {
    return null;
  }

  return useVirtualizer({
    count: tableData.value.length,
    getScrollElement: () => scrollElement.value || null,
    estimateSize: () => 36, // 恢复固定行高36px
  });
});

// 获取虚拟项 - 使用 computed 包装，并处理虚拟化器为空的情况
const virtualRows = computed(() => {
  const v = virtualizer.value;
  return v ? v.value.getVirtualItems() : [];
});

// 获取总高度
const totalSize = computed(() => {
  const v = virtualizer.value;
  return v ? v.value.getTotalSize() : 0;
});

// 测量元素函数 - 修复ref类型
const measureElement = (el: any) => {
  if (!el || !virtualizer.value) {
    return;
  }
  virtualizer.value.value.measureElement(el);
  return undefined;
};

// 计算虚拟表格高度
const calculateVirtualTableHeight = () => {
  nextTick(() => {
    const windowHeight = window.innerHeight;
    const headerHeight = 80; // csv-header 高度
    const progressHeight = importing.value ? 80 : 0; // 进度条高度
    const padding = 40; // 上下内边距
    const headerRowHeight = 40; // 表头行高度

    const availableHeight =
      windowHeight - headerHeight - progressHeight - padding - headerRowHeight;
    virtualTableHeight.value = `${Math.max(400, availableHeight)}px`;
  });
};

// 计算动态列宽
const dynamicColumnWidth = computed(() => {
  if (!scrollElement.value) return 100;

  const containerWidth = scrollElement.value.clientWidth;
  const rowNumberWidth = 60; // 行号列固定宽度
  const availableWidth = containerWidth - rowNumberWidth;
  const minColumnWidth = 120; // 最小列宽

  // 计算平均列宽
  const averageWidth = Math.floor(availableWidth / cols.value);

  // 如果平均宽度小于最小宽度，使用最小宽度
  return Math.max(averageWidth, minColumnWidth);
});

// 组件挂载时初始化
onMounted(() => {
  initializeTable();
  calculateVirtualTableHeight();
});
</script>

<style scoped>
.csv-header {
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  padding: 0 20px;
  height: 80px;
}

.controls {
  display: flex;
  gap: 20px;
  align-items: center;
  flex-wrap: wrap;
  width: 100%;
}

.file-controls {
  display: flex;
  gap: 12px;
  align-items: center;
}

.table-controls {
  display: flex;
  gap: 8px;
  align-items: center;
  border-left: 1px solid #e4e7ed;
  padding-left: 20px;
}

.table-info {
  font-size: 12px;
  color: #909399;
  margin-left: 8px;
}

.csv-main {
  padding: 20px;
  background-color: #fff;
  overflow: auto;
}

.virtual-table-container {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  overflow: hidden;
  background-color: #fff;
}

.table-header-container {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
  margin-bottom: 0;
}

.header-row {
  display: flex;
  width: 100%;
}

.header-cell {
  border-right: 1px solid #e4e7ed;
  padding: 8px;
  text-align: center;
  font-weight: 600;
  color: #606266;
  flex-shrink: 0;
  box-sizing: border-box;
}

.row-number-header {
  width: 60px;
  min-width: 60px;
  max-width: 60px;
  background-color: #fafafa;
}

.virtual-table-body {
  position: relative;
  overflow: auto;
}

.table-row {
  display: flex;
  width: 100%;
  border-bottom: 1px solid #e4e7ed;
}

.table-cell {
  border-right: 1px solid #e4e7ed;
  flex-shrink: 0;
  position: relative;
  box-sizing: border-box;
}

.row-number-cell {
  width: 60px;
  min-width: 60px;
  max-width: 60px;
  background-color: #fafafa;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

.data-cell {
  padding: 0;
}

.cell-input {
  width: 100%;
  height: 36px;
  border: none;
  outline: none;
  padding: 8px 12px;
  font-size: 14px;
  background: transparent;
  transition: background-color 0.2s;
  box-sizing: border-box;
}

.cell-input:focus {
  background-color: #f0f9ff;
  box-shadow: inset 0 0 0 1px #409eff;
}

.cell-input:hover {
  background-color: #fafafa;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .csv-header {
    padding: 0 10px;
    height: auto;
    min-height: 80px;
  }

  .controls {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .table-controls {
    border-left: none;
    border-top: 1px solid #e4e7ed;
    padding-left: 0;
    padding-top: 12px;
  }

  .csv-main {
    padding: 10px;
  }

  .cell-input {
    min-width: 80px;
    font-size: 12px;
  }

  .table-info {
    font-size: 11px;
  }
}

/* 删除按钮样式 */
.header-content {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.row-number-content {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 8px 4px;
}

.delete-btn {
  position: absolute;
  background: #f56c6c;
  color: white;
  border: none;
  border-radius: 50%;
  width: 18px;
  height: 18px;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.delete-btn:hover {
  background: #e54545;
}

.delete-col-btn {
  top: 2px;
  right: 2px;
}

.delete-col-btn:hover {
  transform: scale(1.1);
}

.delete-row-btn {
  top: 50%;
  right: 2px;
  transform: translateY(-50%);
}

.delete-row-btn:hover {
  transform: translateY(-50%) scale(1.1);
}

.table-header:hover .delete-btn,
.row-number-cell:hover .delete-btn {
  opacity: 1;
}

/* 确保表头和行号单元格有足够的空间 */
.table-header {
  position: relative;
  padding: 8px 24px 8px 8px; /* 右侧留出删除按钮空间 */
}

.row-number-cell {
  position: relative;
  padding: 0;
  min-width: 60px; /* 增加宽度以容纳删除按钮 */
}

/* 响应式调整 */
@media (max-width: 768px) {
  .delete-btn {
    opacity: 1; /* 在移动端始终显示删除按钮 */
    width: 16px;
    height: 16px;
    font-size: 11px;
  }

  .table-header {
    padding: 6px 20px 6px 6px;
  }

  .row-number-cell {
    min-width: 50px;
  }
}

.import-progress {
  background-color: #f8f9fa;
  border-bottom: 1px solid #e4e7ed;
  padding: 15px 20px;
  animation: slideDown 0.3s ease-out;
}

.progress-text {
  margin-top: 8px;
  font-size: 14px;
  color: #606266;
  font-weight: 500;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>
